home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / PKTDRVR.C < prev    next >
C/C++ Source or Header  |  1997-07-30  |  14KB  |  587 lines

  1. /* Driver for FTP Software's packet driver interface. (PC specific code)
  2.  * Rewritten Feb 1996 for DPMI with DJGPP Phil Karn
  3.  */
  4. #include "global.h"
  5. #ifdef PACKET
  6. #include <sys/types.h>
  7. #include <go32.h>
  8. #include <dos.h>
  9. #include <dpmi.h>
  10.  
  11. #include "proc.h"
  12. #include "netuser.h"
  13. #include "enet.h"
  14. #include "trace.h"
  15. #include "pktdrvr.h"
  16. #include "devparam.h"
  17.  
  18. #if !defined(_lint)
  19. static char rcsid[] OPTIONAL = "$Id: pktdrvr.c,v 1.16 1997/07/31 00:44:20 root Exp root $";
  20. #endif
  21.  
  22. #define    C_FLAG    1
  23. static long access_type(int intno,int if_class,int if_type,
  24.     int if_number, uint rm_segment,uint rm_offset );
  25. static int driver_info(int intno,int handle,int *version,
  26.     int *class,int *type,int *number,int *basic);
  27. static int release_type(int intno,int handle);
  28. static int get_address(int intno,int handle,uint8 *buf,int len);
  29. #if 0
  30. static int set_rcv_mode(int intno,int handle,int mode);
  31. #endif
  32. static int pk_raw(struct iface *iface,struct mbuf *bp);
  33. static int pk_stop(struct iface *iface);
  34. static void pkint(_go32_dpmi_registers *reg);
  35.  
  36. static struct pktdrvr Pktdrvr[PK_MAX];
  37. static int Derr;
  38.  
  39. static void pk_rx(int dev,void *p1,void *p2);
  40.  
  41.  
  42. /*
  43.  * Send routine for packet driver
  44.  */
  45.  
  46. int
  47. pk_send(
  48. struct mbuf *bp,        /* Buffer to send */
  49. struct iface *iface,        /* Pointer to interface control block */
  50. uint32 gateway OPTIONAL,    /* Ignored  */
  51. int prec OPTIONAL,
  52. int del OPTIONAL,
  53. int tput OPTIONAL,
  54. int rel OPTIONAL
  55. ){
  56.     if (iface == NULL)    {
  57.         free_p (bp);
  58.         return -1;
  59.     }
  60.     return (*iface->raw) (iface, bp);
  61. }
  62.  
  63.  
  64.  
  65. /* Send raw packet (caller provides header) */
  66. static int
  67. pk_raw(
  68. struct iface *iface,    /* Pointer to interface control block */
  69. struct mbuf *bp        /* Data field */
  70. ){
  71. _go32_dpmi_registers reg;
  72. struct pktdrvr *pp;
  73. int16 size;
  74. int offset;
  75. struct mbuf *bp1;
  76.  
  77.     pp = &Pktdrvr[iface->dev];
  78.     size = len_p (bp);
  79.  
  80.     dump (iface, IF_TRACE_OUT, pp->class, bp);
  81.     iface->rawsndcnt++;
  82.     iface->lastsent = secclock();
  83.  
  84.     /* Perform class-specific processing, if any */
  85.     switch (pp->class){
  86.         case CL_ETHERNET:
  87.             if (size < RUNT)    {
  88.                 /* Pad the packet out to the minimum */
  89.                 /* Do it securely with zeros */
  90.                 if ((bp1 = alloc_mbuf (RUNT-size)) == NULLBUF)    {
  91.                     free_p (bp);
  92.                     return -1;
  93.                 }
  94.  
  95.                 memset (bp1->data, 0, RUNT-size);
  96.                 bp1->cnt = RUNT - size;
  97.                 append (&bp, bp1);
  98.                 size = RUNT;
  99.             }
  100.             break;
  101.         case CL_KISS:
  102.             /* This *really* shouldn't be done here, but it was the
  103.              * easiest way. Put the type field for KISS TNC on front.
  104.              */
  105.             if ((bp1 = pushdown (bp, 1)) == NULLBUF)     {
  106.                 free_p (bp);
  107.                 return -1;
  108.             }
  109.             bp = bp1;
  110.             bp->data[0] = PARAM_DATA;
  111.             size++;
  112.             break;
  113.         default:
  114.             break;
  115.     }
  116.  
  117.     /* Copy packet to contiguous real mode buffer */
  118.     offset = 0;
  119.     while(bp != NULL){
  120.         dosmemput(bp->data, bp->cnt, _go32_info_block.linear_address_of_transfer_buffer+offset);
  121.         offset += bp->cnt;
  122.         bp = free_mbuf (bp);
  123.     }
  124.     /* Call the packet driver to send it */
  125.     memset (®, 0, sizeof(reg));
  126.     reg.h.ah = SEND_PKT;
  127.     reg.x.si = _go32_info_block.linear_address_of_transfer_buffer & 15;
  128.     reg.x.ds = _go32_info_block.linear_address_of_transfer_buffer >> 4;
  129.     reg.x.cx = size;
  130.     (void) _go32_dpmi_simulate_int (pp->intno, ®);
  131.     if (reg.x.flags & C_FLAG){
  132.         Derr = reg.h.dh;
  133.         return -1;
  134.     }
  135.     return 0;
  136. }
  137.  
  138.  
  139.  
  140. /* Packet driver receive upcall routine. Called by the packet driver TSR
  141.  * twice for each incoming packet: first with ax == 0 to allocate a buffer,
  142.  * and then with ax == 1 to signal completion of the copy.
  143.  */
  144. static void
  145. pkint(_go32_dpmi_registers *reg)
  146. {
  147. int i;
  148. uint len,blen;
  149. int i_state;
  150. struct pktdrvr *pp;
  151.  
  152.     i_state = disable();
  153.     /* This is not really legal, since handles are not guaranteed to
  154.      * be globally unique. But it's extremely expedient.
  155.      */
  156.     for (i = 0; i < PK_MAX; i++)    {
  157.         if (Pktdrvr[i].handle == reg->x.bx)
  158.             break;
  159.     }
  160.     if (i == PK_MAX)    {
  161.         restore (i_state);
  162.         reg->x.es = reg->x.di = 0;
  163.         return;    /* Unknown handle */
  164.     }
  165.     pp = &Pktdrvr[i];
  166.     len = reg->x.cx;
  167.  
  168.     switch (reg->x.ax){
  169.         case 0:    /* Space allocate call */
  170.             if ((int32) (len + sizeof(len)) > pp->dossize - pp->cnt)    {
  171.                 /* Buffer overflow */
  172.                 reg->x.es = 0;
  173.                 reg->x.di = 0;
  174.                 pp->overflows++;
  175.                 break;
  176.             }
  177.             if ((int32) (pp->wptr + len + sizeof(len)) > pp->dossize)    {
  178.                 /* Not enough room at end of DOS buffer for length
  179.                  * plus data, so write zero length and wrap around
  180.                  */
  181.                 uint zero = 0;
  182.                 pp->cnt += pp->dossize - pp->wptr;
  183.                 dosmemput (&zero, sizeof(zero), pp->dosbase + pp->wptr);
  184.                 pp->wptr = 0;
  185.             }
  186.             /* Write length into DOS buffer */
  187.             dosmemput (&len, sizeof(len), pp->dosbase + pp->wptr);
  188.             pp->wptr += (long) sizeof(len);
  189.             pp->cnt += (long) sizeof(len);
  190.             /* Pass new pointer to packet driver */
  191.             reg->x.es = (pp->dosbase + pp->wptr) / 16;
  192.             reg->x.di = (pp->dosbase + pp->wptr) % 16;
  193.             break;
  194.         case 1:    /* Packet complete call */
  195.             /* blen is len rounded up to next boundary, to keep the
  196.              * next packet on a clean boundary
  197.              */
  198.             blen = (len + sizeof(len) - 1) & ~(sizeof(len) - 1);
  199.             pp->wptr += (long) blen;
  200.             pp->cnt += (long) blen;
  201.             if ((int32) (pp->wptr + sizeof(len)) > pp->dossize)    {
  202.                 /* No room left for another len field, wrap */
  203.                 pp->cnt += pp->dossize - pp->wptr;
  204.                 pp->wptr = 0;
  205.             }
  206.             ksignal (&pp->cnt, 1);
  207.             break;
  208.         default:
  209.             break;
  210.     }
  211.     restore (i_state);
  212. }
  213.  
  214.  
  215.  
  216. /* Shut down the packet interface */
  217. static int
  218. pk_stop(
  219. struct iface *iface
  220. ){
  221. struct pktdrvr *pp;
  222. _go32_dpmi_seginfo dosmem;
  223.  
  224.     pp = &Pktdrvr[iface->dev];
  225.     /* Call driver's release_type() entry */
  226.     if (release_type (pp->intno, pp->handle) == -1)
  227.         printf ("%s: release_type error code %u\n", iface->name, Derr);
  228.  
  229.     pp->iface = NULL;
  230.     dosmem.size = pp->dossize / 16;
  231.     dosmem.rm_segment = pp->dosbase / 16;
  232.     (void) _go32_dpmi_free_dos_memory (&dosmem);
  233.     (void) _go32_dpmi_free_real_mode_callback (&pp->rmcb_seginfo);
  234.     return 0;
  235. }
  236.  
  237.  
  238.  
  239. /* Attach a packet driver to the system
  240.  * argv[0]: hardware type, must be "packet"
  241.  * argv[1]: software interrupt vector, e.g., x7e
  242.  * argv[2]: interface label, e.g., "trw0"
  243.  * argv[3]: receive buffer size in kb
  244.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  245.  * argv[5]: IP address (optional)
  246.  */
  247. int
  248. pk_attach(
  249. int argc,
  250. char *argv[],
  251. void *p
  252. ){
  253. struct iface *if_pk;
  254. int class,type;
  255. char sig[9];
  256. unsigned int intno;
  257. int i;
  258. struct pktdrvr *pp;
  259. char tmp[25];
  260. char *cp;
  261. unsigned long pkt_addr;
  262. unsigned short vec[2];
  263. _go32_dpmi_seginfo dosmem;
  264. #ifdef    ARCNET
  265. static uint8 arcip[] = {ARC_IP};
  266. static uint8 arcarp[] = {ARC_ARP};
  267. #endif
  268.  
  269.     for (i = 0; i < PK_MAX; i++)    {
  270.         if (Pktdrvr[i].iface == NULL)
  271.             break;
  272.     }
  273.     if (i >= PK_MAX)    {
  274.         printf ("Too many packet drivers\n");
  275.         return -1;
  276.     }
  277.     if (if_lookup (argv[2]) != NULL){
  278.         printf ("Interface %s already exists\n", argv[2]);
  279.         return -1;
  280.     }
  281.     intno = htoi (argv[1]);
  282.     /* Verify that there's really a packet driver there, so we don't
  283.      * go off into the ozone (if there's any left)
  284.      */
  285.     dosmemget (intno * 4, 4, vec);
  286.     pkt_addr = vec[1] * 16 + vec[0];
  287.     if (pkt_addr == 0)    {
  288.         printf ("No packet driver loaded at int 0x%x\n", intno);
  289.         return -1;
  290.     }
  291.     dosmemget (pkt_addr + 3, 9, sig);
  292.     if (strcmp (sig, "PKT DRVR") != 0)    {
  293.         printf ("No packet driver loaded at int 0x%x\n", intno);
  294.         return -1;
  295.     }
  296.     /* Find out what we've got */
  297.      if (driver_info ((int) intno, -1, NULL, &class, &type, NULL, NULL) < 0)    {
  298.         printf ("driver_info call failed\n");
  299.         return -1;
  300.     }
  301.     pp = &Pktdrvr[i];
  302.     dosmem.size = 64 * atoi(argv[3]); /* KB -> paragraphs */
  303.     if (_go32_dpmi_allocate_dos_memory (&dosmem))    {
  304.         printf ("DOS memory allocate failed for %d, max size = %d\n", atoi(argv[3]) * 1024, dosmem.size * 16);
  305.         return -1;
  306.     }
  307.     pp->dossize = (long) (dosmem.size * 16);
  308.     pp->dosbase = dosmem.rm_segment * 16;
  309.     pp->overflows = pp->wptr = pp->rptr = pp->cnt = 0;
  310.  
  311.     if_pk = (struct iface *) callocw (1, sizeof(struct iface));
  312.     if_pk->name = strdup(argv[2]);
  313.     if (argc > 5)
  314.         if_pk->addr = resolve (argv[5]);
  315.     else
  316.         if_pk->addr = Ip_addr;
  317.  
  318.     if_pk->mtu = atoi (argv[4]);
  319.     if_pk->dev = i;
  320.     if_pk->raw = pk_raw;
  321.     if_pk->stop = pk_stop;
  322.     pp->intno = (int) intno;
  323.     pp->iface = if_pk;
  324.  
  325.     pp->rmcb_seginfo.pm_offset = (int) pkint;
  326.     if ((i = _go32_dpmi_allocate_real_mode_callback_retf (&pp->rmcb_seginfo,
  327.         &pp->rmcb_registers)) != 0)    {
  328.         printf ("real mode callback alloc failed: %d\n", i);
  329.         return -1;
  330.     }
  331.     pp->handle = access_type ((int) intno, class, ANYTYPE, 0, pp->rmcb_seginfo.rm_segment,
  332.         pp->rmcb_seginfo.rm_offset);
  333.  
  334.     switch (class)    {
  335.         case CL_ETHERNET:
  336.             (void) setencap(if_pk,"Ethernet");
  337.  
  338.             /**** temp set multicast flag ****/
  339. #if 0
  340.             i = set_rcv_mode (intno, pp->handle, 5);
  341.             printf ("set_rcv_mode returns %d, Derr = %d\n", i, Derr);
  342. #endif
  343.  
  344.             /* Get hardware Ethernet address from driver */
  345.             if_pk->hwaddr = mallocw (EADDR_LEN);
  346.             (void) get_address ((int) intno, pp->handle, (unsigned char *) if_pk->hwaddr, EADDR_LEN);
  347.             if (if_pk->hwaddr[0] & 1)    {
  348.                 printf ("Warning! Interface '%s' has a multicast address:", if_pk->name);
  349.                 printf (" (%s)\n", (*if_pk->iftype->format)(tmp,if_pk->hwaddr));
  350.             }
  351.             break;
  352. #ifdef    ARCNET
  353.         case CL_ARCNET:
  354.             if_pk->send = anet_send;
  355.             if_pk->output = anet_output;
  356.             /* Get hardware ARCnet address from driver */
  357.             if_pk->hwaddr = mallocw (AADDR_LEN);
  358.             get_address (intno, pp->handle, if_pk->hwaddr, AADDR_LEN);
  359.             break;
  360. #endif
  361.         case CL_SERIAL_LINE:
  362.             (void) setencap (if_pk, "SLIP");
  363.             break;
  364. #ifdef    AX25
  365.         case CL_KISS:    /* Note that the raw routine puts on the command */
  366.         case CL_AX25:
  367.             (void) setencap (if_pk, "AX25");
  368.             if_pk->hwaddr = mallocw (AXALEN);
  369.             memcpy (if_pk->hwaddr, Mycall, AXALEN);
  370.             break;
  371. #endif
  372.         case CL_SLFP:
  373.             (void) setencap (if_pk, "SLFP");
  374.             if_pk->send = pk_send;
  375.             (void) get_address ((int) intno, pp->handle, (uint8 *) &if_pk->addr, 4);
  376.             break;
  377.         default:
  378.             printf ("Packet driver has unsupported class %u\n", class);
  379.             free (if_pk->name);
  380.             free (if_pk);
  381.             return -1;
  382.     }
  383.     pp->class = class;
  384.     if_pk->next = Ifaces;
  385.     Ifaces = if_pk;
  386.  
  387.     cp = if_name (if_pk, " rx");
  388.     if_pk->rxproc = newproc (cp, 768, pk_rx, if_pk->dev, if_pk, pp, 0);
  389.     free (cp);
  390.     return 0;
  391. }
  392.  
  393.  
  394.  
  395. static long
  396. access_type(
  397. int intno,
  398. int if_class,
  399. int if_type,
  400. int if_number,
  401. uint rm_segment,
  402. uint rm_offset
  403. ){
  404. _go32_dpmi_registers reg;
  405.  
  406.     memset (®, 0, sizeof(reg));
  407.     reg.h.ah = ACCESS_TYPE;    /* Access_type() function */
  408.     reg.h.al = if_class;    /* Class */
  409.     reg.x.bx = if_type;    /* Type */
  410.     reg.h.dl = if_number;    /* Number */
  411.     reg.x.es = rm_segment;    /* Address of rm receive handler */
  412.     reg.x.di = rm_offset;
  413.     (void) _go32_dpmi_simulate_int (intno, ®);
  414.     if (reg.x.flags & C_FLAG)    {
  415.         Derr = reg.h.dh;
  416.         return -1;
  417.     } else
  418.         return reg.x.ax;
  419. }
  420.  
  421.  
  422.  
  423. static int
  424. release_type(
  425. int intno,
  426. int handle
  427. ){
  428. _go32_dpmi_registers reg;
  429.  
  430.     memset (®, 0, sizeof(reg));
  431.     reg.x.bx = handle;
  432.     reg.h.ah = RELEASE_TYPE;
  433.     (void) _go32_dpmi_simulate_int (intno, ®);
  434.     if (reg.x.flags & C_FLAG)    {
  435.         Derr = reg.h.dh;
  436.         return -1;
  437.     } else
  438.         return 0;
  439. }
  440.  
  441.  
  442.  
  443. static int
  444. driver_info(
  445. int intno,
  446. int handle,
  447. int *version,
  448. int *class,
  449. int *type,
  450. int *number,
  451. int *basic
  452. ){
  453. _go32_dpmi_registers reg;
  454.  
  455.     memset (®, 0, sizeof(reg));
  456.     reg.h.ah = DRIVER_INFO;
  457.     reg.x.bx = handle;
  458.     reg.h.al = 0xff;
  459.     (void) _go32_dpmi_simulate_int (intno, ®);
  460.     if (reg.x.flags & C_FLAG)    {
  461.         Derr = reg.h.dh;
  462.         return -1;
  463.     }
  464.     if(version != NULL)
  465.         *version = reg.x.bx;
  466.     if(class != NULL)
  467.         *class = reg.h.ch;
  468.     if(type != NULL)
  469.         *type = reg.x.dx;
  470.     if(number != NULL)
  471.         *number = reg.h.cl;
  472.     if(basic != NULL)
  473.         *basic = reg.h.al;
  474.     return 0;
  475. }
  476.  
  477.  
  478.  
  479. static int
  480. get_address(
  481. int intno,
  482. int handle,
  483. uint8 *buf,
  484. int len
  485. ){
  486. _go32_dpmi_registers reg;
  487.  
  488.     memset (®, 0, sizeof(reg));
  489.     reg.h.ah = GET_ADDRESS;
  490.     reg.x.bx = handle;
  491.     reg.x.di = _go32_info_block.linear_address_of_transfer_buffer & 15;
  492.     reg.x.es = _go32_info_block.linear_address_of_transfer_buffer >> 4;
  493.     reg.x.cx = len;
  494.     (void) _go32_dpmi_simulate_int (intno, ®);
  495.     if (reg.x.flags & C_FLAG)    {
  496.         Derr = reg.h.dh;
  497.         return -1;
  498.     }
  499.     dosmemget (_go32_info_block.linear_address_of_transfer_buffer, len, buf);
  500.     return 0;
  501. }
  502.  
  503.  
  504.  
  505. #if 0
  506. static int
  507. set_rcv_mode(
  508. int intno,
  509. int handle,
  510. int mode
  511. ){
  512. _go32_dpmi_registers reg;
  513.  
  514.     memset (®, 0, sizeof(reg));
  515.     reg.h.ah = SET_RCV_MODE;
  516.     reg.x.cx = mode;
  517.     reg.x.bx = handle;
  518.     (void) _go32_dpmi_simulate_int (intno, ®);
  519.     if (reg.x.flags & C_FLAG)    {
  520.         Derr = reg.h.dh;
  521.         return -1;
  522.     }
  523.     return 0;
  524. }
  525. #endif
  526.  
  527.  
  528. static void
  529. pk_rx(
  530. int dev,
  531. void *p1,
  532. void *p2
  533. ) {
  534. struct iface *iface = (struct iface *) p1;
  535. struct pktdrvr *pp = (struct pktdrvr *) p2;
  536. uint len,blen;    /* len type must match size field in pkint */
  537. struct mbuf *bp;
  538. int cadj;
  539.  
  540. loop:
  541. #if 0
  542.     while ((void) disable(), i = (volatile int) pp->cnt, (void) enable(), i == 0)
  543. #else
  544.     while (pp->cnt == 0)
  545. #endif
  546.         kwait (&pp->cnt);
  547.  
  548.     cadj = 0;
  549.     /* Extract size */
  550.     dosmemget (pp->dosbase + pp->rptr, sizeof(len), &len);
  551.     if (len == 0)    {
  552.         /* Writer wrapped around */
  553.         cadj += pp->dossize - pp->rptr;
  554.         pp->rptr = 0;
  555.         dosmemget (pp->dosbase, sizeof(len), &len);
  556.     }
  557.     /* Copy the packet into an mbuf and queue for the router */
  558.     bp = ambufw (len + sizeof(struct iface *));
  559.     bp->data += sizeof(struct iface *);
  560. #ifdef    debug
  561.     printf ("overf %d cnt %d start %d len %d\n", pp->overflows,
  562.         pp->cnt, pp->rptr + sizeof(len), len);
  563. #endif
  564.     dosmemget (pp->dosbase + pp->rptr + sizeof(len), len, bp->data);
  565.     bp->cnt = len;
  566.     (void) net_route (iface, pp->class, bp);
  567.  
  568.     /* figure length rounded up to next boundary */
  569.     blen = sizeof(len) + (len + sizeof(len) - 1) & ~(sizeof(len)-1);
  570.  
  571.     cadj += (int) blen;
  572.     pp->rptr += (long) blen;
  573.     if ((int32) (pp->rptr + sizeof(len)) > pp->dossize)    {
  574.         cadj += pp->dossize - pp->rptr;
  575.         pp->rptr = 0;
  576.     }
  577.     (void) disable();
  578.     pp->cnt -= cadj;
  579.     (void) enable();
  580.  
  581.     goto loop;
  582. }
  583.  
  584.  
  585. #endif /* PACKET */
  586.  
  587.